import * as XLSX from 'xlsx-js-style';
import moment from 'moment'; // 导入时间过滤器
//导出Excel文件
export const exportData: any = (
  row: any = {
    thead: [], //表头
    tbody: [], //表内容
    fileName: '文件名称', //文件名称
    isSummary: false, //是否统计条数
  },
  data?: any,
) => {
  const _thead = row.thead.filter((el: any) => !el.hidden);
  const maxDepth: number = getMaxDepth(_thead); //最大层数;
  let wsThead: any[] = [];
  for (let index = 0; index < maxDepth; index++) {
    wsThead[index] = [];
  }
  let _theadNew: any = []; //表头key
  // 合并表头单元格
  const merges: any[] = [];
  setHeader(_thead, 1, maxDepth); //设置表头信息
  // 将 JSON 数据转换为工作表所需格式
  const wsTbody: any[] = row.tbody.map((el: any) => {
    return _theadNew.map((item: any) => (el[item.prop] || el[item.prop] === 0 ? el[item.prop] : ''));
  });
  const wsData: any[] = [...wsThead, ...wsTbody];
  if (row.isSummary) {
    const wsSummary: any[] = _theadNew.map((item: any, index: number) => {
      return index === 0 ? `共计 ${wsTbody.length} 条数据` : '';
    });
    wsData.push(wsSummary);
    mergesRange({
      startCol: 0, //开始列号
      firstRow: wsData.length - 1, //开始行号
      endCol: _theadNew.length - 1, //结束列号
      lastRow: wsData.length - 1, //结束行号
    });
  }
  const worksheet = XLSX.utils.aoa_to_sheet(wsData);
  const workbook = XLSX.utils.book_new(); // 创建一个新的工作簿
  // 添加自动筛选
  worksheet['!autofilter'] = { ref: `A${maxDepth}:${getExcelColumnName(_theadNew.length)}${maxDepth}` }; // 假设表头位于A1到B1
  //
  // 表头样式
  const headerStyle = createHeaderStyle();
  // 初始化一个数组用于保存每列最大宽度，初始值设为表头的宽度（如果有的话）
  // 设置默认最小/最大列宽及扩展因子
  const config = {
    defaultMinWidth: 10,
    defaultMaxWidth: 120,
    widthExpansionFactor: 1, // 可按需调大以适配 emoji 或全角字符
    padding: 4, // 额外留白空间
  };
  // 初始化每列最大宽度数组
  const maxColumnWidths: number[] = Array.from({ length: wsData[0]?.length || 0 }, () => 0);
  // 遍历数据行，更新每列最大宽度
  wsData.forEach((row) => {
    row.forEach((cell: any, index: number) => {
      const cellStr = (cell?.toString() ?? '').trim();
      // 计算字符宽度：中文 +2，其他 +1
      let cellLength = 0;
      for (let char of cellStr) {
        cellLength += /[\u4e00-\u9fa5]/.test(char) ? 2 : 1;
      }

      // 更新最大列宽
      if (cellLength > maxColumnWidths[index]) {
        maxColumnWidths[index] = cellLength;
      }
    });
  });
  // 应用计算结果到 worksheet 的列宽配置
  worksheet['!cols'] = maxColumnWidths.map((width) => ({
    wch: Math.min(Math.max(Math.ceil(width * config.widthExpansionFactor) + config.padding, config.defaultMinWidth), config.defaultMaxWidth),
  }));
  worksheet['!merges'] = merges;
  // 给所有数据单元格添加边框
  const allCellsStyle = { border: createBorderStyle() };
  for (let R = 0; R < wsData.length; ++R) {
    for (let C = 0; C < wsData[R].length; ++C) {
      let cellAddress = XLSX.utils.encode_cell({ c: C, r: R });
      if (!worksheet[cellAddress]) {
        worksheet[cellAddress] = { v: '', s: {} };
      }
      if (!worksheet[cellAddress].s) {
        worksheet[cellAddress].s = {};
      }
      Object.assign(worksheet[cellAddress].s, {
        ...allCellsStyle,
        alignment: { horizontal: _theadNew[C].align || 'left', vertical: 'center' }, // 文字居中
      });
    }
  }
  // 应用表头样式
  for (let i = 0; i < _theadNew.length; i++) {
    for (let n = 0; n < wsThead.length; n++) {
      let cellAddress = XLSX.utils.encode_cell({ c: i, r: n });
      if (worksheet[cellAddress]) {
        worksheet[cellAddress].s = headerStyle;
      }
    }
    if (row.isSummary) {
      let cellSummary = XLSX.utils.encode_cell({ c: i, r: wsData.length - 1 });
      if (worksheet[cellSummary]) {
        worksheet[cellSummary].s = headerStyle;
      }
    }
  }
  // 把工作表加入到工作簿中
  XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
  // 生成Excel文件并触发下载
  const wopts: any = { bookType: 'xlsx', type: 'array' };
  const wbout = XLSX.write(workbook, wopts);
  const blob = new Blob([wbout], { type: 'application/octet-stream' });
  const link = document.createElement('a');
  link.href = URL.createObjectURL(blob);
  const time = moment(new Date()).format('YYYYMMDDHHmmss');
  link.download = `${row.fileName}${time}.xlsx`;
  link.click();
  URL.revokeObjectURL(link.href);
  data.loading = false;
  function getExcelColumnName(columnIndex: number) {
    let columnName = '';
    let dividend = columnIndex;
    let modulo;

    while (dividend > 0) {
      modulo = (dividend - 1) % 26;
      columnName = String.fromCharCode(65 + modulo) + columnName;
      dividend = Math.floor((dividend - modulo) / 26);
    }

    return columnName;
  }

  // 创建边框样式
  function createBorderStyle(color = '000000') {
    return {
      top: { style: 'thin', color: { auto: 1 } },
      left: { style: 'thin', color: { auto: 1 } },
      bottom: { style: 'thin', color: { auto: 1 } },
      right: { style: 'thin', color: { auto: 1 } },
    };
  }

  // 创建表头样式
  function createHeaderStyle() {
    return {
      fill: { fgColor: { rgb: 'e0e6ff' } }, // 黄色背景
      font: { bold: false },
      border: createBorderStyle(), // 添加边框样式
      alignment: { horizontal: 'center', vertical: 'center' }, // 文字居中
    };
  }
  //计算thead数组中children字段的最大深度
  function setHeader(arr: any[], Depth: number = 1, maxDepth: number, startCol: number = 0) {
    if (arr && arr.length) {
      let _startCol = 0;
      arr.forEach((el: any, index: number) => {
        wsThead[Depth - 1].push(el.label);
        if (el.children && el.children.length > 0) {
          //判断子节点数量
          let _countNodes = countNodes(el.children);
          for (let index = 1; index < _countNodes; index++) {
            wsThead[Depth - 1].push('');
          }
          mergesRange({
            startCol: _startCol, //开始列号
            firstRow: Depth - 1, //开始行号
            endCol: _startCol + _countNodes - 1, //结束列号
            lastRow: Depth - 1, //结束行号
          });
          _startCol += _countNodes;
          setHeader(el.children, Depth + 1, maxDepth, _startCol);
        } else {
          _theadNew.push(el);
          //判断层深数
          if (Depth < maxDepth) {
            for (let index = 0; index < maxDepth - Depth; index++) {
              wsThead[Depth + index].push('');
            }
            mergesRange({
              startCol: _startCol, //开始列号
              firstRow: Depth - 1, //开始行号
              endCol: _startCol, //结束列号
              lastRow: maxDepth - 1, //结束行号
            });
          }
          _startCol++;
        }
      });
    }
  }
  //设置合并单元格
  function mergesRange(
    range: any = {
      startCol: 0, //开始列号
      firstRow: 0, //开始行号
      endCol: 0, //结束列号
      lastRow: 0, //结束行号
    },
  ) {
    const _range = { s: { c: range.startCol, r: range.firstRow }, e: { c: range.endCol, r: range.lastRow } };
    merges.push(_range);
  }
  //获取子节点数量
  function countNodes(arr: any[]) {
    // 如果不是数组，则返回0，因为这不是一个节点
    if (!Array.isArray(arr)) return 0;
    let count = 0; // 初始化计数器
    // 遍历数组中的每个元素
    for (let item of arr) {
      if (Array.isArray(item.children) && item.children.length > 0) {
        // 如果是数组，则递归调用countNodes，并将结果加到计数器上
        count += countNodes(item.children);
      } else {
        // 如果是普通元素，则直接增加计数器
        count += 1;
      }
    }
    // 返回当前数组的节点数加上当前数组本身作为一个节点（如果数组不为空）
    return count;
  }
  //计算thead数组中children字段的最大深度
  function getMaxDepth(arr: any[]) {
    // 如果不是数组，则返回深度0
    if (!Array.isArray(arr)) return 0;
    // 如果是空数组，其深度视为1
    if (arr.length === 0) return 1;
    // 遍历数组中的每个元素，并递归计算它们的深度
    let maxChildDepth = 0;
    for (let item of arr) {
      maxChildDepth = Math.max(maxChildDepth, getMaxDepth(item.children));
    }
    // 当前数组的深度为其最深层子数组的深度加1
    return 1 + maxChildDepth;
  }
};
